package org.fjsei.yewu.job.jobs;

import md.cm.unit.Unit;
import org.fjsei.yewu.job.SplitRepoJob;
import org.fjsei.yewu.job.util.Constant;
import lombok.extern.slf4j.Slf4j;
import org.fjsei.yewu.repository.StoreSync;
import org.fjsei.yewu.repository.StoreSyncRepository;
import org.fjsei.yewu.repository.maint.SplJob;
import org.fjsei.yewu.repository.maint.SplJobRepository;
import org.fjsei.yewu.service.third.InfRecvConvert;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.Date;
import java.util.UUID;
import java.util.function.Function;

//原本的 implements Job
//不能加 @RequiredArgsConstructor 报错，
@Slf4j
@DisallowConcurrentExecution
@PersistJobDataAfterExecution
@Service        //不加上 @Component 运行是可以，IDEA爆红的。
public class DeviceSyncJob extends InfRecvConvert implements SplitRepoJob {
//    @PersistenceContext(unitName = "entityManagerFactorySei")
//    private EntityManager emSei;                //EntityManager相当于hibernate.Session：
    @Value("${sei.isp.unitname:福建省特种设备检验研究院}")
    private String ispUnitName;
    private volatile boolean interrupted = false; // 中断标志
    private JobKey jobKey;      // Job 的唯一标识
    @Autowired  protected SplJobRepository splJobRepository;
    private SplJob splJob;
    @Autowired  protected StoreSyncRepository storeSyncRepository;
    private Unit ispUnit;
    private JobExecutionContext context;

    @Override
    public boolean isInterrupt() {
        return interrupted;
    }

    @Override
    public boolean executeSlice(JobKey  jobKey,SplJob  splJob) throws SchedulerException{
        this.jobKey=jobKey;
        if(null==ispUnit)   ispUnit=units.findUnitByCompany_Name(ispUnitName);
        Function<StoreSync, String>  sliceJob= parb ->{
            if("OK".equals(parb.getFail()))       return null;
            else syncEqp单设备OD并发(parb, ispUnit);
            return null;
        };
        //后面StoreSync.class是实体投影；
        return runSlice(splJob,storeSyncRepository, sliceJob, StoreSync.class,UUID.class);
    }

    @Override
    public SplJobRepository splJobRepo() {
        return splJobRepository;
    }

    @Override
    public void setSplJob(SplJob splJob) {
        this.splJob=splJob;
    }
    @Override
    public SplJob getSplJob() {
        return this.splJob;
    }

    @Override
    public void setContext(JobExecutionContext context) {
       this.context=context;
    }

    @Override
    public JobExecutionContext getContext() {
        return this.context;
    }

    @Override
    public void interrupt() throws UnableToInterruptJobException {
        interrupted = true; // 设置中断标志为 true
        log.info("Job with JobName {}, GroupName {} is started at {}", jobKey.getName(), jobKey.getGroup(), Constant.SIMPLE_DATE_FORMAT.format(new Date()));
    }

    public <T> void syncEqp单设备OD并发(T inObj, Unit ispUnit) {
        String result="";
        StoreSync parb= (StoreSync)inObj;
        try {
             result=getDeviceFromOld(this.jobKey,parb, ispUnit);
        } catch (Exception e) {
            e.printStackTrace();
            result= e.getMessage().length() > 250 ? e.getMessage().substring(0, 250) : e.getMessage();
    //            throw new CommonGraphQLException("inf", e.getMessage());
        }
        if(StringUtils.hasText(result) )    parb.setFail(result);
        //else     parb.setFail("OK");
        storeSyncRepository.save(parb);
    }
}

/*
集群模式Quartz：若作业节点挂起的是无法转交job的，必须要关机重启被挂启问题节点才能恢复job运行。
使用静态变量来存储 ApplicationContext 并不是最佳实践，因为它可能导致内存泄漏（特别是在Web应用程序中），并且使得单元测试更加困难。更好的做法是使用依赖注入来直接注入所需的bean，而不是通过 ApplicationContext 来获取它们。
然而，在Quartz Job等场景中，由于Quartz本身不直接支持Spring的依赖注入，因此有时需要使用像上面这样的工具类来获取 ApplicationContext，然后从中获取所需的bean。在这些情况下，请确保你了解这种方法的潜在风险，并考虑在可能的情况下使用更优雅的解决方案（如自定义 JobFactory）。
    @Autowired
    private Provider<StoreSyncRepository> storeSyncRepositoryProvider;
     public void someMethod() {
        StoreSyncRepository storeSyncRepository = storeSyncRepositoryProvider.get();
        // 使用storeSyncRepository的方法
    }
* */